package com.lxw.nonghe.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.lxw.nonghe.common.Result;
import com.lxw.nonghe.entity.User;
import com.lxw.nonghe.service.RoleService;
import com.lxw.nonghe.service.UserService;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/auth")
public class LoginController {

    private static final Logger log = LoggerFactory.getLogger(LoginController.class);

    // Redis key前缀
    private static final String USER_KEY_PREFIX = "user:";
    private static final String TOKEN_KEY_PREFIX = "token:";
    private static final String PERMISSION_KEY_PREFIX = "permission:";
    // 设置Redis过期时间(单位：小时)
    private static final long REDIS_EXPIRE_HOURS = 24;

    @Autowired
    private UserService userService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @PostMapping("/login")
    public Result<Map<String, Object>> login(@RequestBody User user) {
        User existingUser = userService.getUserByUsername(user.getUsername());
        if (existingUser == null) {
            log.info("用户 {} 登录失败，用户不存在", user.getUsername());
            return Result.error("用户不存在");
        }

        if (BCrypt.checkpw(user.getPassword(), existingUser.getPassword())) {
            // 生成 token
            StpUtil.login(existingUser.getUserId());
            String token = StpUtil.getTokenValue();
            //获取行政编码
            String parentCode = existingUser.getParentCode();
            // 获取用户权限列表
            List<String> permissionList = userService.getUserPermissions(existingUser.getUserId());
            // 获取用户角色信息
            String role = roleService.getRoleById(Long.valueOf(existingUser.getRoleId())).getRoleName();

            log.info("User {} permissions after login: {}", existingUser.getUserId(), permissionList);

            try {
                // 将用户信息、token和权限保存到 Redis
                String userIdKey = String.valueOf(existingUser.getUserId());
                redisTemplate.opsForValue().set(USER_KEY_PREFIX + userIdKey, existingUser, REDIS_EXPIRE_HOURS, TimeUnit.HOURS);
                redisTemplate.opsForValue().set(TOKEN_KEY_PREFIX + userIdKey, token, REDIS_EXPIRE_HOURS, TimeUnit.HOURS);
                redisTemplate.opsForValue().set(PERMISSION_KEY_PREFIX + userIdKey, permissionList, REDIS_EXPIRE_HOURS, TimeUnit.HOURS);
            } catch (Exception e) {
                log.error("存储用户信息到 Redis 失败", e);
                return Result.error("登录时出现异常，请稍后重试");
            }

            // 构造返回数据
            Map<String, Object> data = new HashMap<>();
            data.put("token", token);
            data.put("role", role);
            data.put("username", existingUser.getUsername());
            data.put("parentCode", parentCode);

            log.info("用户 {} 登录成功", existingUser.getUsername());
            return Result.success("登录成功", data);
        } else {
            log.info("用户 {} 登录失败，密码错误", user.getUsername());
            return Result.error("密码错误");
        }
    }

    @PostMapping("/logout")
    public Result<String> logout() {
        try {
            if (!StpUtil.isLogin()) {
                log.info("退出登录失败，当前未登录");
                return Result.error("当前未登录");
            }

            Long userId = StpUtil.getLoginIdAsLong();
            String userIdKey = String.valueOf(userId);

            // 清除 Redis 中存储的所有相关数据
            redisTemplate.delete(USER_KEY_PREFIX + userIdKey);
            redisTemplate.delete(TOKEN_KEY_PREFIX + userIdKey);
            redisTemplate.delete(PERMISSION_KEY_PREFIX + userIdKey);

            StpUtil.logout();
            log.info("用户 {} 退出登录成功", userId);
            return Result.success("退出成功");
        } catch (Exception e) {
            log.error("退出登录时发生异常", e);
            return Result.error("退出登录失败，请重试");
        }
    }

    public static String encryptPassword(String password) {
        return BCrypt.hashpw(password, BCrypt.gensalt());
    }
}
